#include "rtc.h"
#define __DEBUG__ 	1
#if __DEBUG__  
#include "uart.h"
    #define DEBUG(format,...)    printf(""format"", ##__VA_ARGS__)  
#else
    #define DEBUG(format,...)  
#endif

#define BCD2INT(valueBCD) 	(uint8_t)((valueBCD&0x0F) + ((valueBCD>>4)&0x0F) * 10)
#define INT2BCD(valueINT)	(uint8_t)(((valueINT/10)<<4)|(valueINT%10))

rtcStruct_t devRTC;
static void RTC_Localtime(void);
static uint8_t RTC_Setting(RTC_BIN_DATE_t* pDate, RTC_BIN_TIME_t* pTime);
void RTC_Init(void) {
	LL_RTC_InitTypeDef RTC_InitStruct = {0};
	LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
	LL_RTC_DateTypeDef RTC_DateStruct = {0};
	if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != 0x32F2){
		LL_RCC_EnableRTC();
	
		/** Initialize RTC and set the Time and Date 
		*/
		RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
		RTC_InitStruct.AsynchPrescaler = 127;
		RTC_InitStruct.SynchPrescaler = 255;
		LL_RTC_Init(RTC, &RTC_InitStruct);
		LL_RTC_SetAsynchPrescaler(RTC, 127);
		LL_RTC_SetSynchPrescaler(RTC, 255);
	
		RTC_TimeStruct.Hours = 18;
		RTC_TimeStruct.Minutes = 16;
		RTC_TimeStruct.Seconds = 55;
		LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_TimeStruct);
		RTC_DateStruct.Day = 22;
		RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_THURSDAY;
		RTC_DateStruct.Month = LL_RTC_MONTH_AUGUST;
		RTC_DateStruct.Year = 19;
		LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_DateStruct);
		LL_RTC_BAK_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
	}
	devRTC.localtime = &RTC_Localtime;
	devRTC.setting   = &RTC_Setting;
	devRTC.localtime();
}

static void RTC_Localtime(void) {
	uint32_t rtcData;
	RTC_BCD_TIME_t *pTime;
	RTC_BCD_DATE_t *pDate;
	
	rtcData = LL_RTC_TIME_Get(RTC);
	pTime = (RTC_BCD_TIME_t*)&rtcData;
	devRTC.time.Second = BCD2INT(pTime->Second);
	devRTC.time.Minute = BCD2INT(pTime->Minute);
	devRTC.time.Hour   = BCD2INT(pTime->Hour);
	
	rtcData = LL_RTC_DATE_Get(RTC);
	pDate = (RTC_BCD_DATE_t*)&rtcData;
	devRTC.date.Week   = BCD2INT(pDate->Week);
	devRTC.date.Day    = BCD2INT(pDate->Day);
	devRTC.date.Month  = BCD2INT(pDate->Month);
	devRTC.date.Year   = BCD2INT(pDate->Year);
}

static uint8_t RTC_Setting(RTC_BIN_DATE_t* pDate, RTC_BIN_TIME_t* pTime) {
	LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
	LL_RTC_DateTypeDef RTC_DateStruct = {0};
	uint8_t result;
	
	RTC_TimeStruct.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
	RTC_TimeStruct.Hours      = pTime->Hour;
	RTC_TimeStruct.Minutes    = pTime->Minute;
	RTC_TimeStruct.Seconds    = pTime->Second;
	result = LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_TimeStruct);
	if(result != SUCCESS) {
		return result;
	}
	
	RTC_DateStruct.Year       = pDate->Year;
	RTC_DateStruct.Month      = pDate->Month;
	RTC_DateStruct.Day        = pDate->Day;
	RTC_DateStruct.WeekDay    = pDate->Week;
	result = LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_DateStruct);
	return result;
}
